package com.zh.oauth.aop;


import com.alibaba.fastjson.JSON;
import com.zh.common.constans.AuthConstant;
import com.zh.common.entity.JSONResult;


import com.zh.oauth.dao.AuthMapper;
import com.zh.oauth.entity.ElecRole;
import com.zh.oauth.entity.ElecUser;
import com.zh.oauth.service.ElecUserService;
import com.zh.oauth.util.RoleUtil;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;

/**
 * code is far away from bug with the animal protecting
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　　┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 *
 * @Description: 权限类操作日志切入
 * @Author: Li.HuiNeng
 * @Create in: 2020-05-30 11:05
 * @Version: 1.0.1
 */
@Aspect
@Component
public class RoleLog {

    private static final Logger log = LoggerFactory.getLogger(RoleLog.class);

    @Qualifier("taskExecutor")
    @Autowired
    private TaskExecutor executor;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ElecUserService service;

    @Autowired
    private AuthMapper mapper;

    @Pointcut("execution(* com.zh.oauth.controller.AuthController.addRole(..))")
    public void addRoleLog() {
    }

    @Async
    @AfterReturning(value = "addRoleLog()", returning = "result")
    public void afterAddRole(@NotNull JoinPoint jp, JSONResult result) {
        Map<String, String> map = new HashMap<>();
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        log.info("####### 角色添加记录 #######");
        String uName = String.valueOf(jp.getArgs()[0]);
        ElecRole role = (ElecRole) jp.getArgs()[1];
        String roleName = role.getRoleName();
        String roleMemo = role.getRoleMemo();
        Long pid = role.getPid();
        Long id = role.getId();
        // 记录值
        map.put("roleName", roleName);
        map.put("roleMemo", roleMemo);
        map.put("pid", String.valueOf(pid));
        map.put("id", String.valueOf(id));
        map.put("des", result.getMessage());
        map.put("notes", apiOperation.notes());
        map.put("success", result.getSuccess() ? "1" : "0");
        String date = String.format("%1$tF %1$tT", new Date());
        map.put("_id", date);
        log.info("操作人：{},目标方法：{}", uName, method.getName());
        mongoTemplate.insert(map, uName + "ROLE");
        if (result.getSuccess()) updateRoleCache(uName);
    }

    @Pointcut("execution(* com.zh.oauth.controller.AuthController.delRole(..))")
    public void delRoleLog() {
    }

    @Async
    @AfterReturning(value = "delRoleLog()", returning = "result")
    public void afterDelRole(@NotNull JoinPoint jp, JSONResult result) {

        log.info("########角色删除日志记录######");
        Map<String, String> map = new HashMap<>();
        Long id = (Long) jp.getArgs()[0];
        String uName = String.valueOf(jp.getArgs()[1]);
        // 记录值
        map.put("id", String.valueOf(id));
        map.put("des", result.getMessage());
        String date = String.format("%1$tF %1$tT", new Date());
        map.put("_id", date);
        map.put("success", result.getSuccess() ? "1" : "0");
        mongoTemplate.insert(map, uName + "ROLE");
        if (result.getSuccess()) updateRoleCache(uName);

    }

    @Pointcut("execution(* com.zh.oauth.controller.AuthController.modRole(..))")
    public void modRoleLog() {
    }

    @Async
    @Before(value = "modRoleLog()")
    public void beforeModRole(@NotNull JoinPoint jp) {
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        Map<String, String> map = new HashMap<>();
        log.info("####### 角色修改记录 #######");
        String uName = null;
        ElecRole role = null;
        ElecRole beforeRole = null;
        try {
            uName = String.valueOf(jp.getArgs()[0]);
            role = (ElecRole) jp.getArgs()[1];
            beforeRole = mapper.getRoleById(role.getId());
            map.put("roleName", "修改前：" + beforeRole.getRoleName() + "。修改后：" + role.getRoleName());
            map.put("pid", "修改前：" + beforeRole.getPid() + "。修改后：" + role.getPid());
            String date = String.format("%1$tF %1$tT", new Date());
            map.put("_id", date);
            map.put("notes", apiOperation.notes());
            log.info("操作人：{},目标方法：{}", uName, method.getName());
            map.put("success", "1");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", "0");
            map.put("err", e.getLocalizedMessage());
            mongoTemplate.insert(map, uName + "ROLE");
        }
        mongoTemplate.insert(map, uName);
        updateRoleCache(uName);

    }

    /**
     * 更新角色Redis缓存
     *
     * @param uName
     */
    private void updateRoleCache(String uName) {
        log.info("#######更新ROLE缓存数据########");
        ElecUser userInfo = new ElecUser();
        try {
            userInfo = JSON.parseObject(JSON.toJSON(redisTemplate.opsForValue().get(uName + AuthConstant.USER_INFO)).toString(), ElecUser.class);
        } catch (Exception e) {
            log.error("未查询到{}用户的缓存信息", uName);
        }
        List<ElecRole> roleList = service.selectRoleByUserId(userInfo.getId());
        redisTemplate.opsForValue().set(uName + AuthConstant.USER_ROLE, RoleUtil.getTreeData(roleList));
        log.info("#####操作日志记录完毕####");
    }

}
